package org.epanetgrid.otimizacao.ag;

import org.jheuristics.ga.DefaultPopulation;
import org.jheuristics.ga.GAConfig;
import org.jheuristics.ga.GAStatus;
import org.jheuristics.ga.Population;
import org.jheuristics.ga.exception.IllegalIndividualException;
import org.jheuristics.ga.operators.PopulationChooser;
import org.jheuristics.ga.operators.Rate;
import org.jheuristics.ga.operators.ReproductionOperator;
import org.jheuristics.ga.operators.Reproductor;
import org.jheuristics.ga.operators.Selector;
import org.jheuristics.ga.operators.reproductors.AbstractReproductorDecorator;

/**
 * Seleciona indiv�duos para fazer a reprodu��o. Caso a reprodu��o seja realizada com sucesso, os filhos
 * s�o adicionados ao resultado, caso contr�rio selecionam-se novos pais para reprodu��o at� que esta 
 * ocorra corretamente, at� atingir a quantidade m�xima de tentativas
 * @author Marcell Manfrin, marcell at ourgrid.org, 2005
 */
public class ReselecaoEmDescarteReproductionOperator extends ReproductionOperator {

	/**
	 *	@see org.jheuristics.ga.operators.ReproductionOperator#ReproductionOperator(Rate, Selector, Reproductor, PopulationChooser, boolean, PopulationChooser, boolean)
	 */
	public ReselecaoEmDescarteReproductionOperator(Rate rate, Selector selector, Reproductor reproductor, PopulationChooser fromPopChooser, boolean cleanAfterFromPop, PopulationChooser toPopChooser, boolean cleanBeforeToPop) {
		super(rate, selector, reproductor, fromPopChooser, cleanAfterFromPop, toPopChooser, cleanBeforeToPop);
	}

	/**
	 * Seleciona indiv�duos para fazer a reprodu��o. Caso a reprodu��o seja realizada com sucesso, os filhos
	 * s�o adicionados ao resultado, caso contr�rio selecionam-se novos pais para reprodu��o at� que esta 
	 * ocorra corretamente, at� atingir a quantidade m�xima de tentativas
	 * @param population
	 * @param status
	 * @param config
	 * @return
	 * @see org.jheuristics.ga.operators.AbstractReproductionOperator#reproduce(org.jheuristics.ga.Population, org.jheuristics.ga.GAStatus, org.jheuristics.ga.GAConfig)
	 */
	protected Population reproduce(Population population, GAStatus status, GAConfig config) {
        Selector selector = getSelector();
        Reproductor reproductor = getReproductor();
        int rate = getRate().rate(status, config);
        int tryOuts = ((AbstractReproductorDecorator) reproductor).getMaxBadReproductionAttempts();

        Population result = new DefaultPopulation();
        if (0 != reproductor.getRequiredNumberOfParents()) {
        	int required = reproductor.getRequiredNumberOfParents();
	        for (int i = 0; i < rate; i++) {
	        	for (int j = 0; j < tryOuts; j++) {
					try {
			            result.addIndividuals(reproductor.reproduce(selector.select(population, required, status, config), status, config));
			            break;
					} catch (IllegalIndividualException e) {
						// try again
					}
	        	}
	        }
        } else {
            result.addIndividuals(reproductor.reproduce(selector.select(population, rate, status, config), status, config));
        }
        return result;
	}

}
